package com.boyinet.imesh2json.netty.server

import com.boyinet.imesh2json.netty.decoder.IMeshMessageDecoder
import com.boyinet.imesh2json.netty.handler.IMeshRequestHandler
import io.netty.bootstrap.ServerBootstrap
import io.netty.channel.ChannelFuture
import io.netty.channel.ChannelInitializer
import io.netty.channel.ChannelOption
import io.netty.channel.nio.NioEventLoopGroup
import io.netty.channel.socket.SocketChannel
import io.netty.channel.socket.nio.NioServerSocketChannel
import io.netty.handler.timeout.IdleStateHandler
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

/**
 * @author lengchunyun
 */
@Component
class NettyServerListener(@Autowired private val iMeshRequestHandler: IMeshRequestHandler) {

    private val log = LoggerFactory.getLogger(NettyServerListener::class.java)

    lateinit var bossGroup: NioEventLoopGroup

    lateinit var workerGroup: NioEventLoopGroup

    lateinit var future: ChannelFuture

    @Throws(InterruptedException::class)
    fun startNettyServer(port: Int) {
        log.info("${Thread.currentThread().name} running")
        bossGroup = NioEventLoopGroup()
        workerGroup = NioEventLoopGroup()
        val serverBootstrap = ServerBootstrap()
        serverBootstrap.group(bossGroup, workerGroup)
            .channel(NioServerSocketChannel::class.java)
            .option(ChannelOption.SO_REUSEADDR, true)
            .option(ChannelOption.SO_BACKLOG, 1024)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .childHandler(object : ChannelInitializer<SocketChannel>() {
                @Throws(Exception::class)
                override fun initChannel(socketChannel: SocketChannel) {
                    //30分钟没有写入踢掉
                    socketChannel.pipeline().addLast(IdleStateHandler(30, 0, 0))
                    socketChannel.pipeline().addLast(IMeshMessageDecoder())
                    socketChannel.pipeline().addLast(iMeshRequestHandler)
                }
            })
        future = serverBootstrap.bind(port).sync()

        if (future.isSuccess) {
            log.info("开启服务器成功....,服务器端口[{}]", port)
        }
    }

    fun shutdown() {
        //优雅退出
        bossGroup.shutdownGracefully()
        workerGroup.shutdownGracefully()
    }
}